package org.cybzacg.convert.factory;


import lombok.extern.slf4j.Slf4j;
import org.cybzacg.convert.context.ConversionContext;
import org.cybzacg.convert.core.AbstractTypeConverter;
import org.cybzacg.convert.core.TypeConverter;
import org.cybzacg.convert.enums.ConversionError;
import org.cybzacg.convert.enums.ConversionType;
import org.cybzacg.convert.enums.SelectionStrategy;
import org.cybzacg.convert.exception.ConversionException;
import org.cybzacg.convert.matcher.ConverterSelector;
import org.cybzacg.convert.matcher.MatchResult;
import org.cybzacg.convert.matcher.SelectionResult;
import org.jetbrains.annotations.NotNull;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 转换器工厂类
 * 使用工厂模式管理各种类型转换器
 *
 * @author cybzacg.blog
 * @version 3.0
 * @since 3.0
 */
@Slf4j
public class ConverterFactory {

    /**
     * 单例实例
     */
    private static final AtomicReference<ConverterFactory> instance = new AtomicReference<>();

    /**
     * 转换器缓存
     */
    private final Map<Class<?>, TypeConverter> converterCache = new ConcurrentHashMap<>();

    /**
     * 转换器类型映射
     */
    private final Map<ConversionType, List<TypeConverter>> typeConverters = new ConcurrentHashMap<>();

    /**
     * 所有转换器列表
     */
    private final List<TypeConverter> allConverters = new ArrayList<>();

    /**
     * 智能转换器选择器
     */
    private final ConverterSelector converterSelector;

    /**
     * 私有构造方法
     */
    private ConverterFactory() {
        this.converterSelector = new ConverterSelector();
    }

    /**
     * 获取工厂实例
     *
     * @return 工厂实例
     */
    public static ConverterFactory getInstance() {
        ConverterFactory current = instance.get();
        if (current == null) {
            synchronized (ConverterFactory.class) {
                current = instance.get();
                if (current == null) {
                    current = new ConverterFactory();
                    instance.set(current);
                }
            }
        }
        return current;
    }


    /**
     * 注册转换器
     *
     * @param converter 转换器
     */
    public void registerConverter(TypeConverter converter) {
        if (converter == null) {
            throw new IllegalArgumentException("转换器不能为null");
        }

        log.debug("注册转换器: {}", converter.getName());

        // 添加到全局列表
        allConverters.add(converter);

        // 按优先级排序
        allConverters.sort(Comparator.comparingInt(TypeConverter::getPriority));

        // 清除缓存
        converterCache.clear();
        typeConverters.clear();

        // 重新构建类型映射
        rebuildTypeMapping();
    }

    /**
     * 重新构建类型映射
     */
    private void rebuildTypeMapping() {
        typeConverters.clear();

        for (TypeConverter converter : allConverters) {
            // 根据转换器支持的类型进行映射
            Class<?> supportedType = converter.getSupportedType();
            if (supportedType != null) {
                ConversionType conversionType = ConversionType.fromTypeName(supportedType.getSimpleName());
                typeConverters.computeIfAbsent(conversionType, k -> new ArrayList<>()).add(converter);
            }
        }

        log.debug("重新构建类型映射完成，共 {} 种类型", typeConverters.size());
    }

    /**
     * 获取转换器
     *
     * @param targetType 目标类型
     * @return 转换器
     * @throws ConversionException 转换器未找到时抛出
     */
    public TypeConverter getConverter(Class<?> targetType) throws ConversionException {
        // 先从缓存获取
        TypeConverter cached = converterCache.get(targetType);
        if (cached != null && cached.isEnabled()) {
            log.debug("从缓存获取转换器: {} -> {}", targetType.getSimpleName(), cached.getName());
            return cached;
        }

        // 查找合适的转换器
        TypeConverter converter = findConverter(targetType);

        if (converter == null) {
            log.error("未找到支持类型 {} 的转换器", targetType.getSimpleName());
            throw new ConversionException(ConversionError.UNSUPPORTED_CONVERSION,
                    "未找到支持类型 " + targetType.getSimpleName() + " 的转换器");
        }

        // 缓存结果
        converterCache.put(targetType, converter);
        log.info("缓存转换器: {} -> {}", targetType.getSimpleName(), converter.getName());

        return converter;
    }

    /**
     * 查找转换器（传统方法）
     *
     * @param targetType 目标类型
     * @return 转换器
     */
    private TypeConverter findConverter(Class<?> targetType) {
        // 遍历所有转换器，找到第一个支持目标类型的转换器
        for (TypeConverter converter : allConverters) {
            if (converter.isEnabled() && converter.supports(targetType)) {
                return converter;
            }
        }

        return null;
    }

    /**
     * 智能获取转换器（带上下文）
     * 使用新的智能选择策略
     *
     * @param sourceType 源类型
     * @param targetType 目标类型
     * @param context 转换上下文
     * @return 转换器
     * @throws ConversionException 转换器未找到时抛出
     */
    public TypeConverter getConverter(Class<?> sourceType, Class<?> targetType, ConversionContext context) throws ConversionException {
        try {
            // 使用智能选择器选择最佳转换器
            SelectionResult result = converterSelector.selectConverter(
                getAllEnabledConverters(), sourceType, targetType, context);

            log.debug("智能选择转换器: {} -> {} -> {}, 原因: {}, 耗时: {}ms",
                     sourceType != null ? sourceType.getSimpleName() : "null",
                     targetType.getSimpleName(),
                     result.getConverter().getName(),
                     result.getSelectionReason(),
                     result.getSelectionTime());

            return result.getConverter();
        } catch (ConversionException e) {
            log.error("智能选择转换器失败: {} -> {}, 错误: {}",
                     sourceType != null ? sourceType.getSimpleName() : "null",
                     targetType.getSimpleName(), e.getMessage());
            throw e;
        }
    }

    /**
     * 智能获取转换器（简化版本）
     *
     * @param sourceType 源类型
     * @param targetType 目标类型
     * @return 转换器
     * @throws ConversionException 转换器未找到时抛出
     */
    public TypeConverter getConverter(Class<?> sourceType, Class<?> targetType) throws ConversionException {
        return getConverter(sourceType, targetType, null);
    }

    /**
     * 检查是否有可用的转换器（智能版本）
     *
     * @param sourceType 源类型
     * @param targetType 目标类型
     * @param context 转换上下文
     * @return 是否有可用转换器
     */
    public boolean hasAvailableConverter(Class<?> sourceType, Class<?> targetType, ConversionContext context) {
        return converterSelector.hasAvailableConverter(getAllEnabledConverters(), sourceType, targetType, context);
    }

    /**
     * 获取所有可用的转换器信息
     *
     * @param sourceType 源类型
     * @param targetType 目标类型
     * @param context 转换上下文
     * @return 匹配结果列表
     */
    public List<MatchResult> getAvailableConverters(
            Class<?> sourceType, Class<?> targetType, ConversionContext context) {
        return converterSelector.getAvailableConverters(getAllEnabledConverters(), sourceType, targetType, context);
    }

    /**
     * 设置选择策略
     *
     * @param strategy 选择策略
     */
    public void setSelectionStrategy(SelectionStrategy strategy) {
        converterSelector.setStrategy(strategy);
        log.info("设置转换器选择策略: {}", strategy.name());
    }

    /**
     * 获取当前选择策略
     *
     * @return 选择策略
     */
    public SelectionStrategy getSelectionStrategy() {
        return converterSelector.getStrategy();
    }

    /**
     * 根据转换类型获取转换器列表
     *
     * @param conversionType 转换类型
     * @return 转换器列表
     */
    public List<TypeConverter> getConvertersByType(ConversionType conversionType) {
        return typeConverters.getOrDefault(conversionType, Collections.emptyList())
                .stream()
                .filter(TypeConverter::isEnabled)
                .collect(Collectors.toList());
    }

    /**
     * 获取所有启用的转换器
     *
     * @return 转换器列表
     */
    public List<TypeConverter> getAllEnabledConverters() {
        return allConverters.stream()
                .filter(TypeConverter::isEnabled)
                .collect(Collectors.toList());
    }

    /**
     * 获取所有转换器
     *
     * @return 转换器列表
     */
    public List<TypeConverter> getAllConverters() {
        return new ArrayList<>(allConverters);
    }

    /**
     * 启用转换器
     *
     * @param converterName 转换器名称
     * @return 是否成功启用
     */
    public boolean enableConverter(String converterName) {
        for (TypeConverter converter : allConverters) {
            if (converter.getName().equals(converterName) && converter instanceof AbstractTypeConverter) {
                ((AbstractTypeConverter) converter).setEnabled(true);
                log.info("启用转换器: {}", converterName);
                return true;
            }
        }
        log.warn("未找到转换器: {}", converterName);
        return false;
    }

    /**
     * 禁用转换器
     *
     * @param converterName 转换器名称
     * @return 是否成功禁用
     */
    public boolean disableConverter(String converterName) {
        for (TypeConverter converter : allConverters) {
            if (converter.getName().equals(converterName) && converter instanceof AbstractTypeConverter) {
                ((AbstractTypeConverter) converter).setEnabled(false);
                // 清除缓存
                converterCache.clear();
                log.info("禁用转换器: {}", converterName);
                return true;
            }
        }
        log.warn("未找到转换器: {}", converterName);
        return false;
    }

    /**
     * 移除转换器
     *
     * @param converterName 转换器名称
     * @return 是否成功移除
     */
    public boolean removeConverter(String converterName) {
        boolean removed = allConverters.removeIf(converter -> converter.getName().equals(converterName));
        if (removed) {
            // 清除缓存
            converterCache.clear();
            typeConverters.clear();
            rebuildTypeMapping();
            log.info("移除转换器: {}", converterName);
        } else {
            log.warn("未找到要移除的转换器: {}", converterName);
        }
        return removed;
    }

    /**
     * 检查是否支持指定类型的转换
     *
     * @param targetType 目标类型
     * @return 是否支持
     */
    public boolean supports(Class<?> targetType) {
        return allConverters.stream()
                .anyMatch(converter -> converter.isEnabled() && converter.supports(targetType));
    }

    /**
     * 获取支持的类型列表
     *
     * @return 支持的类型列表
     */
    public Set<Class<?>> getSupportedTypes() {
        return allConverters.stream()
                .filter(TypeConverter::isEnabled)
                .map(TypeConverter::getSupportedType)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
    }

    /**
     * 清除所有转换器
     */
    public void clearAllConverters() {
        log.info("清除所有转换器");
        allConverters.clear();
        converterCache.clear();
        typeConverters.clear();
    }

    /**
     * 获取工厂统计信息
     *
     * @return 统计信息
     */
    public FactoryStatistics getStatistics() {
        return new FactoryStatistics(
                allConverters.size(),
                (int) allConverters.stream().filter(TypeConverter::isEnabled).count(),
                converterCache.size(),
                typeConverters.size(),
                getSupportedTypes().size()
        );
    }

    /**
     * 工厂统计信息
     */
    public record FactoryStatistics(int totalConverters, int enabledConverters, int cacheSize, int typeMappingSize,
                                    int supportedTypes) {

        @NotNull
        @Override
        public String toString() {
            return String.format(
                    "FactoryStatistics{总转换器数=%d, 启用转换器数=%d, 缓存大小=%d, 类型映射数=%d, 支持类型数=%d}",
                    totalConverters, enabledConverters, cacheSize, typeMappingSize, supportedTypes
            );
        }
    }
}
